#include "stdafx.h"
//From   http://www.codeguru.com/bitmap/SmoothBitmapResizing.html
#include "..\ActiveWnd\dibapi.h"
#include "..\ActiveWnd\ICanvas.h"

int *CreateCoeffInt(int nLen, int nNewLen, BOOL bShrink)
{
 int nSum = 0, nSum2;
 int *pRes = new int[2 * nLen];
 int *pCoeff = pRes;
 int nNorm = (bShrink) 
           ? (nNewLen << 12) / nLen : 0x1000;
 int	nDenom = (bShrink)? nLen : nNewLen;

 ::ZeroMemory(pRes, 2 * nLen * sizeof(int));
 for(int i = 0; i < nLen; i++, pCoeff += 2)
 {
  nSum2 = nSum + nNewLen;
  if(nSum2 > nLen)
  {
   *pCoeff = ((nLen - nSum) << 12) / nDenom;
   pCoeff[1] = ((nSum2 - nLen) << 12) / nDenom;
   nSum2 -= nLen;
  }
  else
  {
   *pCoeff = nNorm;
   if(nSum2 == nLen)
   {
    pCoeff[1] = -1;
    nSum2 = 0;
   }
  }
  nSum = nSum2;
 }
 
 return pRes;
}

void ShrinkDataInt(BYTE *pInBuff, 
                   WORD wWidth, 
                   WORD wHeight,
                   BYTE *pOutBuff, 
                   WORD wNewWidth, 
                   WORD wNewHeight)
{
	BYTE  *pLine = pInBuff, *pPix;
	BYTE  *pOutLine = pOutBuff;
	DWORD dwInLn = (wWidth*2+7)&0xFFFFFFF8;//(3 * wWidth + 3) & ~3;
	DWORD dwOutLn = (wNewWidth*2+7)&0xFFFFFFF8;//(3 * wNewWidth + 3) & ~3;
	int   x, y, i;
	BOOL  bCrossRow, bCrossCol;
	int   *pRowCoeff = CreateCoeffInt(wWidth, 
								   wNewWidth, 
								   TRUE);
	int   *pColCoeff = CreateCoeffInt(wHeight, 
								   wNewHeight, 
								   TRUE);
	int   *pXCoeff, *pYCoeff = pColCoeff;
	DWORD dwBuffLn = 3 * wNewWidth * sizeof(DWORD);
	DWORD *pdwBuff = new DWORD[6 * wNewWidth];
	DWORD *pdwCurrLn = pdwBuff, 
	   *pdwCurrPix, 
	   *pdwNextLn = pdwBuff + 3 * wNewWidth;
	DWORD dwTmp, *pdwNextPix;

	::ZeroMemory(pdwBuff, 2 * dwBuffLn);

	y = 0;
	while(y < wNewHeight)
	{
		pPix = pLine;
		pLine += dwInLn;

		pdwCurrPix = pdwCurrLn;
		pdwNextPix = pdwNextLn;

		x = 0;
		pXCoeff = pRowCoeff;
		bCrossRow = pYCoeff[1] > 0;
		while(x < wNewWidth)
		{
			dwTmp = *pXCoeff * *pYCoeff;
			//for(i = 0; i < 3; i++)
			//	pdwCurrPix[i] += dwTmp * pPix[i];
			pdwCurrPix[0] +=dwTmp * ((WPixel *)pPix)->red;
			pdwCurrPix[1] +=dwTmp * ((WPixel *)pPix)->green;
			pdwCurrPix[2] +=dwTmp * ((WPixel *)pPix)->blue;
			bCrossCol = pXCoeff[1] > 0;
			if(bCrossCol)
			{
				dwTmp = pXCoeff[1] * *pYCoeff;
				//for(i = 0, ii = 3; i < 3; i++, ii++)
				//	pdwCurrPix[ii] += dwTmp * pPix[i];
				pdwCurrPix[3] +=dwTmp * ((WPixel *)pPix)->red;
				pdwCurrPix[4] +=dwTmp * ((WPixel *)pPix)->green;
				pdwCurrPix[5] +=dwTmp * ((WPixel *)pPix)->blue;
			}
			if(bCrossRow)
			{
				dwTmp = *pXCoeff * pYCoeff[1];
				//for(i = 0; i < 3; i++)
				//	pdwNextPix[i] += dwTmp * pPix[i];
				pdwNextPix[0] +=dwTmp * ((WPixel *)pPix)->red;
				pdwNextPix[1] +=dwTmp * ((WPixel *)pPix)->green;
				pdwNextPix[2] +=dwTmp * ((WPixel *)pPix)->blue;

				if(bCrossCol)
				{
					dwTmp = pXCoeff[1] * pYCoeff[1];
					//for(i = 0, ii = 3; i < 3; i++, ii++)
					//	pdwNextPix[ii] += dwTmp * pPix[i];
					pdwNextPix[3] +=dwTmp * ((WPixel *)pPix)->red;
					pdwNextPix[4] +=dwTmp * ((WPixel *)pPix)->green;
					pdwNextPix[5] +=dwTmp * ((WPixel *)pPix)->blue;
				}
			}
			if(pXCoeff[1])
			{
				x++;
				pdwCurrPix += 3;
				pdwNextPix += 3;
			}
			pXCoeff += 2;
			pPix += 2;
		}
		if(pYCoeff[1])
		{
	   // set result line
			pdwCurrPix = pdwCurrLn;
			pPix = pOutLine;
			//for(i = 3 * wNewWidth; i > 0; i--, pdwCurrPix++, pPix++)
			//	*pPix = ((LPBYTE)pdwCurrPix)[3];
			for(i = 0; i<wNewWidth; i++,pdwCurrPix+=3,pPix+=2)
			{
				((WPixel *)pPix)->red = ((LPBYTE)pdwCurrPix)[3];
				((WPixel *)pPix)->green = ((LPBYTE)pdwCurrPix)[7];
				((WPixel *)pPix)->blue = ((LPBYTE)pdwCurrPix)[11];
			}
	   // prepare line buffers
			pdwCurrPix = pdwNextLn;
			pdwNextLn = pdwCurrLn;
			pdwCurrLn = pdwCurrPix;
			::ZeroMemory(pdwNextLn, dwBuffLn);

			y++;
			pOutLine += dwOutLn;
		}
		pYCoeff += 2;
	}

	delete [] pRowCoeff;
	delete [] pColCoeff;
	delete [] pdwBuff;
} 

void EnlargeDataInt(BYTE *pInBuff, 
	WORD wWidth, 
	WORD wHeight,
	BYTE *pOutBuff, 
	WORD wNewWidth, 
	WORD wNewHeight)
{
	BYTE  *pLine = pInBuff, 
	*pPix = pLine, 
	*pPixOld, 
	*pUpPix, 
	*pUpPixOld;
	BYTE  *pOutLine = pOutBuff, *pOutPix;
	DWORD dwInLn = (wWidth*2+7)&0xFFFFFFF8;//(3 * wWidth + 3) & ~3;
	DWORD dwOutLn = (wNewWidth*2+7)&0xFFFFFFF8;//(3 * wNewWidth + 3) & ~3;
	int   x, y;
	BOOL  bCrossRow, bCrossCol;
	int   *pRowCoeff = CreateCoeffInt(wNewWidth, wWidth, FALSE);
	int   *pColCoeff = CreateCoeffInt(wNewHeight, wHeight, FALSE);
	int   *pXCoeff, *pYCoeff = pColCoeff;
	DWORD dwTmp, dwPtTmp[3];

	y = 0;
	while(y < wHeight)
	{
		bCrossRow = pYCoeff[1] > 0;
		x = 0;
		pXCoeff = pRowCoeff;
		pOutPix = pOutLine;
		pOutLine += dwOutLn;
		pUpPix = pLine;
		if(pYCoeff[1])
		{
			y++;
			pLine += dwInLn;
			pPix = pLine;
		}

		while(x < wWidth)
		{
			bCrossCol = pXCoeff[1] > 0;
			pUpPixOld = pUpPix;
			pPixOld = pPix;
			if(pXCoeff[1])
			{
				x++;
				pUpPix += 2;
				pPix += 2;
			}

			dwTmp = *pXCoeff * *pYCoeff;

			//for(i = 0; i < 3; i++)
			//	dwPtTmp[i] = dwTmp * pUpPixOld[i];
			dwPtTmp[0] = dwTmp * ((WPixel*)pUpPixOld)->red;
			dwPtTmp[1] = dwTmp * ((WPixel*)pUpPixOld)->green;
			dwPtTmp[2] = dwTmp * ((WPixel*)pUpPixOld)->blue;

			if(bCrossCol)
			{
				dwTmp = pXCoeff[1] * *pYCoeff;
				//for(i = 0; i < 3; i++)
				//	dwPtTmp[i] += dwTmp * pUpPix[i];
				dwPtTmp[0] += dwTmp * ((WPixel*)pUpPix)->red;
				dwPtTmp[1] += dwTmp * ((WPixel*)pUpPix)->green;
				dwPtTmp[2] += dwTmp * ((WPixel*)pUpPix)->blue;
			}

			if(bCrossRow)
			{
				dwTmp = *pXCoeff * pYCoeff[1];
				//for(i = 0; i < 3; i++)
				//	dwPtTmp[i] += dwTmp * pPixOld[i];
				dwPtTmp[0] += dwTmp * ((WPixel*)pPixOld)->red;
				dwPtTmp[1] += dwTmp * ((WPixel*)pPixOld)->green;
				dwPtTmp[2] += dwTmp * ((WPixel*)pPixOld)->blue;
				if(bCrossCol)
				{
					dwTmp = pXCoeff[1] * pYCoeff[1];
					//for(i = 0; i < 3; i++)
					//	dwPtTmp[i] += dwTmp * pPix[i];
					dwPtTmp[0] += dwTmp * ((WPixel*)pPix)->red;
					dwPtTmp[1] += dwTmp * ((WPixel*)pPix)->green;
					dwPtTmp[2] += dwTmp * ((WPixel*)pPix)->blue;
				}
			}

			//for(i = 0; i < 3; i++, pOutPix++)
			//	*pOutPix = ((LPBYTE)(dwPtTmp + i))[3];
			((WPixel *)pOutPix)->red = ((LPBYTE)dwPtTmp)[3];
			((WPixel *)pOutPix)->green = ((LPBYTE)dwPtTmp)[7];
			((WPixel *)pOutPix)->blue = ((LPBYTE)dwPtTmp)[11];
			pOutPix += 2;
			pXCoeff += 2;
		}
		pYCoeff += 2;
	}

	delete [] pRowCoeff;
	delete [] pColCoeff;
} 
